using Forecast.Business;
using Forecast.Database;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Text;

namespace Forecast.Business.Test
{
    [TestFixture]
    public class TestNewOffer
    {
        #region Variables

        private NewOffer _newOffer;
        private Player _buyer, _seller;
        private Holding _sellerHolding;
        private Prediction _prediction;

        #endregion
        #region Setup / Teardown

        [SetUp]
        public void Init()
        {
            _newOffer = new NewOffer();
            _buyer = Mocks.GetBuyer();
            _seller = Mocks.GetSeller();
            _sellerHolding = Mocks.GetSellerHolding();
            _prediction = Mocks.GetPrediction();
        }

        #endregion
        #region Tests for Buy

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyPlayerNull()
        {
            _newOffer.Buy(null, _prediction, 30, 25, DateTime.Today.AddDays(10)); 
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void BuyPredictionNull()
        {
            _newOffer.Buy(_buyer, null, 30, 25, DateTime.Today.AddDays(10));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyNoPredictions()
        {
            _newOffer.Buy(_buyer, _prediction, 0, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyNegativeNumberOfPredictions()
        {
            _newOffer.Buy(_buyer, _prediction, -7, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyNoPrice()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 0, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyNegativePrice()
        {
            _newOffer.Buy(_buyer, _prediction, 10, -10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyTooHighPrice()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 110, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyMaxPrice()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 100, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyMinDate()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 10, DateTime.MinValue);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyAfterEndDateOfPrediction()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 10, DateTime.MaxValue);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyDateToday()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 10, DateTime.Today);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyTooManyPredictions()
        {
            _newOffer.Buy(_buyer, _prediction, 1000, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyNonActivePrediction()
        {
            _prediction.IsActive = false;
            _newOffer.Buy(_buyer, _prediction, 10, 50, DateTime.Now.AddDays(2));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void BuyClosedPrediction()
        {
            _prediction.IsClosed = true;
            _newOffer.Buy(_buyer, _prediction, 10, 50, DateTime.Now.AddDays(2));
        }

        [Test]
        public void BuyNormal()
        {
            _newOffer.Buy(_buyer, _prediction, 10, 50, DateTime.Today.AddDays(2));
            Assert.AreEqual(MockIds.BUYER, _newOffer.NewOfferPlayer.Id);
            Assert.AreEqual(1000, _newOffer.NewOfferPlayer.Cash);
            Assert.AreEqual(DateTime.Today.AddDays(2), _newOffer.NewOfferOffer.EndDate);
            Assert.AreEqual(false, _newOffer.NewOfferOffer.IsAccepted);
            Assert.AreEqual(true, _newOffer.NewOfferOffer.IsActive);
            Assert.AreEqual(true, _newOffer.NewOfferOffer.IsBuy);
            Assert.AreEqual(10, _newOffer.NewOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.BUYER, _newOffer.NewOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _newOffer.NewOfferOffer.PredictionId);
            Assert.AreEqual(50, _newOffer.NewOfferOffer.Price);
        }

        #endregion
        #region Tests for Sell

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellPlayerNull()
        {
            _newOffer.Sell(null, _sellerHolding, _prediction, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellHoldingNull()
        {
            _newOffer.Sell(_seller, null, _prediction, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void SellPredictionNull()
        {
            _newOffer.Sell(_seller, _sellerHolding, null, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellNoPredictions()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 0, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellNegativeNumberOfPredictions()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, -7, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellNoPrice()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 0, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellNegativePrice()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, -10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellTooHighPrice()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 110, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellMaxPrice()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 100, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellMinDate()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.MinValue);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellAfterEndDateOfPrediction()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.MaxValue);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellNonActivePrediction()
        {
            _prediction.IsActive = false;
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 50, DateTime.Now.AddDays(2));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellClosedPrediction()
        {
            _prediction.IsClosed = true;
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 50, DateTime.Now.AddDays(2));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellDateToday()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.Today);
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellTooManyPredictions()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 100, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellPlayerDoesNotMatchHolding()
        {
            _seller.Id = 399;
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellHoldingDoesNotMatchPrediction()
        {
            _prediction.Id = 777;
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        [ExpectedException(typeof(ArgumentException))]
        public void SellOwnsNoPredictions()
        {
            _sellerHolding.NumPredictions = 0;
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 10, DateTime.Today.AddDays(7));
        }

        [Test]
        public void SellNormal()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 10, 15, DateTime.Today.AddDays(7));
            Assert.AreEqual(65, _newOffer.NewOfferHolding.NumPredictions);
            Assert.AreEqual(DateTime.Today.AddDays(7), _newOffer.NewOfferOffer.EndDate);
            Assert.AreEqual(true, _newOffer.NewOfferOffer.IsActive);
            Assert.AreEqual(false, _newOffer.NewOfferOffer.IsBuy);
            Assert.AreEqual(10, _newOffer.NewOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _newOffer.NewOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _newOffer.NewOfferOffer.PredictionId);
            Assert.AreEqual(15, _newOffer.NewOfferOffer.Price);
        }

        [Test]
        public void SellAll()
        {
            _newOffer.Sell(_seller, _sellerHolding, _prediction, 75, 60, DateTime.Today.AddDays(14));
            Assert.AreEqual(0, _newOffer.NewOfferHolding.NumPredictions);
            Assert.AreEqual(DateTime.Today.AddDays(14), _newOffer.NewOfferOffer.EndDate);
            Assert.AreEqual(true, _newOffer.NewOfferOffer.IsActive);
            Assert.AreEqual(false, _newOffer.NewOfferOffer.IsBuy);
            Assert.AreEqual(75, _newOffer.NewOfferOffer.NumPredictions);
            Assert.AreEqual(MockIds.SELLER, _newOffer.NewOfferOffer.PlayerId);
            Assert.AreEqual(MockIds.PREDICTION, _newOffer.NewOfferOffer.PredictionId);
            Assert.AreEqual(60, _newOffer.NewOfferOffer.Price);
        }

        #endregion
    }
}
